package com.zhuozhou.jdyc.base;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Intent;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;

import com.google.gson.JsonParseException;
import com.trello.rxlifecycle2.LifecycleTransformer;
import com.zhuozhou.jdyc.api.ApiRetrofit;
import com.zhuozhou.jdyc.api.ApiServiceHelper;
import com.zhuozhou.jdyc.util.log.LogUtil;

import org.json.JSONException;

import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;

/**
 * Create by CherishTang on 2020/3/19 0019
 * describe:baseViewMode封装
 */
public class BaseViewModel<V extends BaseView> extends AndroidViewModel {

    //离开页面，是否取消网络
    private CompositeDisposable compositeDisposable;
    /**
     * 如果开启，同一url还在请求网络时，不会
     */
    public ArrayList<String> onNetTags;

    private String dialogMessage = "正在加载，请稍后...";
    private LifecycleTransformer objectLifecycleTransformer;
    protected V baseView;
    private boolean isShowToast = true;
    private boolean isShowDialog;
    protected ApiServiceHelper apiServiceHelper = ApiRetrofit.getInstance().getApiService();


    public BaseViewModel(@NonNull Application application) {
        super(application);
        this.isShowDialog = true;
    }

//    public static class Factory<V extends BaseView> implements ViewModelProvider.Factory {
//        protected V baseView;
//        protected boolean isShowDialog;
//        private Application application;
//        public Factory(@NonNull Application application,V baseView) {
//            this.baseView = baseView;
//            this.application = application;
//        }
//
//        @NonNull
//        @Override
//        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
//            return (T)new BaseViewModel(application,baseView);
//        }
//    }

    protected void setBaseView(V baseView) {
        this.baseView = baseView;
    }


    public void setShowDialog(boolean showDialog) {
        isShowDialog = showDialog;
    }

    public V getBaseView() {
        return baseView;
    }

    public boolean isShowDialog() {
        return isShowDialog;
    }

    @Override
    protected void onCleared() {
        super.onCleared();
    }

    public void setDialogMessage(String dialogMessage) {
        this.dialogMessage = dialogMessage;
    }

    private void addDisposable(Disposable disposable) {
        if (compositeDisposable == null) {
            compositeDisposable = new CompositeDisposable();
        }
        compositeDisposable.add(disposable);
    }

    private void removeDisposable() {
        if (compositeDisposable != null) {
            compositeDisposable.dispose();
        }
    }

    public void setObjectLifecycleTransformer(LifecycleTransformer objectLifecycleTransformer) {
        this.objectLifecycleTransformer = objectLifecycleTransformer;
    }

    /**
     * activity/fragment的 onActivityResult回调
     *
     * @param requestCode 请求code
     * @param resultCode  回调code
     * @param data        回调数据
     */
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    }

    protected Consumer<Disposable> disposableBefore = new Consumer<Disposable>() {
        @Override
        public void accept(Disposable disposable) throws Exception {
            addDisposable(disposable);
            if (baseView != null && isShowDialog) {
                baseView.showLoading(dialogMessage);
            }
        }
    };

    //把统一操作全部放在这，不会重连
    @SuppressLint("CheckResult")
    protected <T> MutableLiveData<T> observe(Observable observable, boolean isShowDialog, final MutableLiveData<T> liveData) {
        this.isShowDialog = isShowDialog;
        return observe(observable, liveData);
    }

    //把统一操作全部放在这，不会重连
    @SuppressLint("CheckResult")
    protected <T> MutableLiveData<T> observe(Observable observable, final MutableLiveData<T> liveData) {
        observable.subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        addDisposable(disposable);
                        if (baseView != null && isShowDialog) {
                            baseView.showLoading(dialogMessage);
                        }
                    }
                })
                .doFinally(() -> {
                    if (baseView != null && isShowDialog) {
                        baseView.hideLoading();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                // .retryWhen(new RetryWithDelay())
                .subscribe(o -> {
                    liveData.postValue((T) o);
                }, consumerError);

        return liveData;
    }

    protected Action finallyAction = new Action() {
        @Override
        public void run() throws Exception {
            if (baseView != null && isShowDialog) {
                baseView.hideLoading();
            }
        }
    };

    protected Consumer consumerError = (Consumer<Throwable>) e -> {
        LogUtil.show("BaseViewModel|系统异常: " + e);

        if (baseView != null && isShowDialog) {
            baseView.hideLoading();
        }
        BaseException be = null;

        if (e != null) {

            if (e instanceof BaseException) {
                be = (BaseException) e;

                //回调到view层 处理 或者根据项目情况处理
                if (baseView != null) {
                    if (isShowToast) {
                        baseView.showToast(be.getErrorMsg());
                    }
                    baseView.onErrorCode(new BaseModelEntity(be.getErrorCode(), be.getErrorMsg()));
                    return;
                }
            } else {
                if (e instanceof HttpException) {
                    if (((HttpException) e).code() == 401) {
                        baseView.showToast("请登录后操作");
                        baseView.onErrorCode(new BaseModelEntity("401", "请登录后操作"));
                        return;
                    }
                    //   HTTP错误
                    be = new BaseException(BaseException.BAD_NETWORK_MSG, e, BaseException.BAD_NETWORK);
                } else if (e instanceof ConnectException
                        || e instanceof UnknownHostException) {
                    //   连接错误
                    be = new BaseException(BaseException.CONNECT_ERROR_MSG, e, BaseException.CONNECT_ERROR);
                } else if (e instanceof InterruptedIOException) {
                    //  连接超时
                    be = new BaseException(BaseException.CONNECT_TIMEOUT_MSG, e, BaseException.CONNECT_TIMEOUT);
                } else if (e instanceof JsonParseException
                        || e instanceof JSONException
                        || e instanceof ParseException) {
                    //  解析错误
                    be = new BaseException(BaseException.PARSE_ERROR_MSG, e, BaseException.PARSE_ERROR);
                } else {
                    be = new BaseException(BaseException.OTHER_MSG, e, BaseException.OTHER);
                }
            }
        } else {
            be = new BaseException(BaseException.OTHER_MSG, e, BaseException.OTHER);
        }
        LogUtil.show("BaseViewModel|异常消息: " + be.getErrorMsg());
        if (baseView != null) {
            baseView.onErrorCode(new BaseModelEntity(be.getErrorCode(), be.getErrorMsg()));
            if (isShowToast) {
                baseView.showToast(be.getErrorMsg());
            }
        }
    };

}
